package com.kakame.codenews.front.article.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import com.kakame.codenews.base.constant.SystemConstant;
import com.kakame.codenews.base.util.DateUtil;
import com.kakame.codenews.base.util.IdUtil;
import com.kakame.codenews.base.web.annotation.CacheOperate;
import com.kakame.codenews.base.web.entity.Page;
import com.kakame.codenews.base.web.enumeration.CacheOperateType;
import com.kakame.codenews.base.web.fast.mapping.common.Article;
import com.kakame.codenews.base.web.fast.mapping.nexus.ArticleComment;
import com.kakame.codenews.base.web.fast.mapping.nexus.CommentComment;
import com.kakame.codenews.base.web.fast.mapping.nexus.UserMessage;
import com.kakame.codenews.base.web.websocket.handler.SiteInnerMessageHandler;
import com.kakame.codenews.front.article.dao.FrontArticleDao;
import com.kakame.codenews.front.article.service.FrontArticleService;
import com.kakame.codenews.front.message.service.FrontMessageService;

/**
 * 前台文章业务实现层
 * @author 何家明 2018年7月4日 下午9:41:39
 */
@Service
public class FrontArticleServiceImpl implements FrontArticleService {

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
	@Resource
	private FrontArticleDao articleDao;
	@Resource
	private FrontMessageService messageService;
	
	@Resource
    public SiteInnerMessageHandler siteInnerMessageHandler;
	
	@Override
	@CacheOperate(operateType = CacheOperateType.SET_AND_COVER)
	public void add(Article article) {
		articleDao.add(article);
	}
	
    @Override
    public int update(Article article) {
        return articleDao.update(article);
    }

	@Override
	public Page<Article> page(Integer pageNo, Integer pageSize) {
		return articleDao.page(pageNo, pageSize);
	}

	@Override
	@CacheOperate(operateType = CacheOperateType.GET, returnType = Article.class)
	public Article get(String articleId) {
		return articleDao.get(articleId);
	}

    @Override
    @CacheOperate(operateType = CacheOperateType.DELETE)
    public int delete(String articleId) {
        return articleDao.delete(articleId);
    }

    @Override
    @CacheOperate(operateType = CacheOperateType.GET, returnType = List.class)
    public List<ArticleComment> listChildComments(String articleId) {
        return articleDao.listChildComments(articleId);
    }

    @Override
    public List<ArticleComment> listCommentRedirectReply(String commentParentId) {
        return articleDao.listCommentRedirectReply(commentParentId);
    }

    @Override
    @CacheOperate(operateType = CacheOperateType.DELETE, deleteCaches = {"listChildComments"}, deleteWithPre = true)
    public Integer insertComment(ArticleComment articleComment) {
        
        // 新消息接收人
        List<String> messageToIds = new ArrayList<>();
        
        IdUtil idWorker = new IdUtil(0, 0);
        
        // 1、插入文章评论
        String articleCommentId = SystemConstant.T_NEXUS_ARTICLE_COMMENT + idWorker.nextId();
        ArticleComment dbAc = ArticleComment.create()
                      .id(articleCommentId)
                      .articleId(articleComment.getArticleId())
                      .commentContent(articleComment.getCommentContent())
                      .commentNum(0)
                      .createTime(articleComment.getCreateTime())
                      .createUserId(articleComment.getCreateUserId())
                      .status(SystemConstant.DATA_STATUS_C)
                      .build();
        articleDao.insertNexusArticleComment(dbAc);
        // 2、插入评论之间的关系
        List<CommentComment> commentReplys = new ArrayList<>();
        if(StringUtils.isNotBlank(articleComment.getId())) {
            // 2.1如果不为空，说明是对评论进行的回复
            // 此时要获取所有的父评论，并生成父评论到此条评论的关系
            List<CommentComment> parentComments = articleDao.listParentComments(articleComment.getId());
            for (CommentComment commentComment : parentComments) {
                messageToIds.add(commentComment.getCreateUserId());
                
                CommentComment cc = CommentComment.create()
                        .id(SystemConstant.T_NEXUS_COMMENT_COMMENT + idWorker.nextId())
                        .commentParentId(commentComment.getCommentId())
                        .commentId(articleCommentId)
                        .distance(commentComment.getDistance() + 1)
                        .status(SystemConstant.DATA_STATUS_C)
                        .build();
                commentReplys.add(cc);
            }
        } else {
            // 2.2如果为空，说明是对文章进行的回复
            CommentComment commentComment = CommentComment.create()
                    .id(SystemConstant.T_NEXUS_COMMENT_COMMENT + idWorker.nextId())
                    .commentParentId(articleComment.getArticleId())
                    .commentId(articleCommentId)
                    .distance(-1)
                    .status(SystemConstant.DATA_STATUS_C)
                    .build();
            commentReplys.add(commentComment);
            
            // 文章的作者也应该作为新消息的接收者
            messageToIds.add(get(articleComment.getArticleId()).getCreateUserId());
        }
        // 2.3插入自己跟自己的关系
        CommentComment commentComment = CommentComment.create()
                .id(SystemConstant.T_NEXUS_COMMENT_COMMENT + idWorker.nextId())
                .commentParentId(articleCommentId)
                .commentId(articleCommentId)
                .distance(0)
                .status(SystemConstant.DATA_STATUS_C)
                .build();
        commentReplys.add(commentComment);
        articleDao.insertNexusCommentComment(commentReplys);
        
        if(StringUtils.isNotBlank(articleComment.getId())) {
            // 对评论进行的回复，更新所有父评论的评论数+1
            articleDao.updateCommentNum(articleCommentId);
        }
        
        List<UserMessage> userMessages = new ArrayList<>();
        for(String toId : messageToIds) {
            // 插入消息
            UserMessage userMessage = UserMessage.create()
                    .id(SystemConstant.T_NEXUS_USER_MESSAGE + idWorker.nextId())
                    .fromId(articleComment.getCreateUserId())
                    .toId(toId)
                    .messageId(articleCommentId)
                    .messageSource(SystemConstant.MESSAGE_SOURCE_ARTICLE_COMMENT)
                    .messageStatus("0")
                    .status(SystemConstant.DATA_STATUS_C)
                    .createUserId(articleComment.getCreateUserId())
                    .createTime(DateUtil.getNow())
                    .build();
            userMessages.add(userMessage);
        }
        messageService.insertNoReadMessage(userMessages);
        
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
            	siteInnerMessageHandler.sendMessageToAllUsers();
            }
        });
        return 1;
    }

}
